from spreadsheetdb import *
from itertools import *
from datetime import datetime
from pprint import pprint

def timestamp(x, desc=True):
  m = -1 if desc else 1
  try:
    return (m * int(x.year), m * int(x.month))
  except:
    return (m * int(x.year), m * 1)

def public(x):
  p = x.get('private')
  return (p == None or str(p).lower()[0] in ['0', 'n'])

def aggregate(p, context):
  aggr = Bundle()

  # Publication aggregation
  renaming = {"inprepandsubmitted": "in preparation and submitted" ,
              "bookchapters": "book chapters"}
  ordering = {
    "journals":         100,
    "conferences":      200,
    "book chapters":    300,
    "books":            400,
    "talks":            600,
    "in preparation and submitted": 700,
  }
  pubs = list(flatten(p['publications']))
  if context == 'public':
    pubs = [x for x in pubs if public(x)]

  for x in pubs:
    x['type'] = renaming.get(x['type'], x['type'])
  aggr.x_pub_year = groupby(sorted(pubs, key=timestamp), key=lambda x: x.year)
  aggr.x_pub_type = groupby(sorted(pubs, key=lambda x: (ordering.get(x.type), timestamp(x))),
               key=lambda x: x.type)

  # Talks

  talks = list(Bundle(x) for x in p['researchactivities']['talksandlectures'] \
               if x['title'])
  for x in talks:
    if x.year and x.month:
      x.date = datetime(int(x.year), int(x.month), 1).strftime("%b %Y")
    else:
      x.date = x.year
  aggr.x_talks = talks

  # Courses
  courses = map(Bundle, p['teaching']['courses'])

  for c in courses:
    if c.coursecode.lower().endswith("u"):
      c.type = "Undergraduate"
    else:
      c.type = "Graduate"
  aggr.x_courses = groupby(
    (Bundle(zip(["code", "type", "title"], x)) for x in sorted(set(
    (c.coursecode, c.type, c.coursetitle) for c in courses))),
    key=lambda x: x.type)

  # Supervision
  def info(s, time=False):
    now = datetime.now()
    try:
      start = datetime(int(s['yearstart']), int(s['monthstart']), 1)
      end = datetime(int(s['yearend']), int(s['monthend']), 1)
    except:
      start = end = now
    if time:
      return (start, end)
    else:
      return "Current" if now <= end else "Past"

  students = sorted(alias(flatten(p['supervision']),
                    thesisprojecttitle="thesistitle"),
                    key=lambda x:(info(x), x.type, info(x, time=True)))
  aggr.x_supervision = groupby(students, key=lambda x: (info(x), x.type))

  aggr.x_students = groupby(sorted(students, key=lambda x:x.type),
                    key=lambda x: x.type)

  # Funding
  fundings = sorted((Bundle(x, status=info(x)) for x in p['funding']['grants']), 
                    key=lambda x: (x.status, x.yearend, x.monthend, x.yearstart,
                    x.yearend, x.title))

  aggr.x_fundings = groupby(fundings, key=lambda x: x.status)

  # Services
  servtypes = (
    ('servicetofaculty', 'Faculty wide services'),
    ('servicetouoit', 'UOIT wide services'),
    ('servicetoprofession', 'Services to the profession'),
    ('servicetocommunity', 'Services to the community'),
  )
  x_services = []
  for (x,label) in servtypes:
    services = p['service'][x]
    x_services.append((label, sorted(services, 
                      key=lambda _: (_['yearstart'], _['monthstart'],
                                     _['yearend'], _['monthend']))))
  aggr.x_services = x_services

  return aggr


def in_daterange(x, start, end):
  if "yearstart" in x:
    y0 = x['yearstart']
    m0 = x['monthstart']
    y1 = x['yearend']
    m1 = x['monthend']
    if y1 == None and m1 == None:
      return True
    else:
      return ((y0,m0) <= start <= (y1,m1)) or ((y0,m0) <= end <= (y1,m1)) \
              or (start <= (y0,m0) <= end) or (start <= (y1,m1) <= end)
  elif "year" in x:
    y = x['year']
    m = x['month']
    return (start <= (y,m) <= end)
  elif "yearsemester" in x:
    y = x['yearsemester']
    m = x['monthsemester']
    return (start <= (y,m) <= end)
  elif "yearapplied" in x:
    y = x['yearapplied']
    m = x['monthapplied']
    return (start <= (y,m) <= end)
  else:
    raise Exception("No timing info.")
    
def restrict_by_date(p, start, end):
  for sheet, content in p.items():
    try:
      for wksheet, rows in content.items():
        newrows = [x for x in rows if in_daterange(x, start, end)] 
        content[wksheet] = newrows
    except:
      pass
